package com.cc.alltype.wechat;

import com.cc.alltype.BusinessException;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chanchaw
 * @create 2024-11-29 15:32
 */
public class WechatQrSceneUtils {
    private static final String QR_SCENE="QR_SCENE";
    private static final String QR_STR_SCENE="QR_STR_SCENE";
    private static final String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";
    private static final String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";
    private static final String MSG_TYPE = "用于兑换二维码的场景值的ticket只支持两个类型：Integer,String";

    /**
     * 获取请求带有场景值的二维码的ticket的url，注意使用 post json 的方式
     * @param token 开发者微信后台与微信服务器通信的token
     * @return 用于请求ticket的url（临时二维码ticket和永久二维码ticket使用同一个url）
     */
    public static String getQrTicketUrl(String token){
        return "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN".replaceAll("TOKEN", token);
    }

    /**
     * 用于换取【临时二维码/永久二维码】的【ticket】的请求用到的参数中的属性
     * action_info = QrSceneWrapper对象，其属性 scene 只有两种类型：String,Integer
     * 本方法返回属性 action_info 的对象
     * @param sceneData
     * @return
     * @param <T>
     */
    public static <T> QrSceneWrapper getQrSceneWrapper(T sceneData){
        if(sceneData instanceof String) return new QrSceneWrapper(new QrSceneString((String)sceneData));
        if(sceneData instanceof Integer) return new QrSceneWrapper(new QrSceneInteger((Integer)sceneData));
        throw new BusinessException(MSG_TYPE);
    }

    public static <T> SceneQRTicketTempReqParam getTempTicketReqParam(T sceneData){
        SceneQRTicketTempReqParam ret = new SceneQRTicketTempReqParam();
        ret.setExpire_seconds(604800);// 单位秒，默认7天，最多30天
        if(sceneData instanceof String) ret.setAction_name(QR_STR_SCENE);
        if(sceneData instanceof Integer) ret.setAction_name(QR_SCENE);
        if(ret.getAction_name() == null) throw new BusinessException(MSG_TYPE);
        ret.setAction_info(getQrSceneWrapper(sceneData));
        return ret;
    }

    public static <T> SceneQRTicketPermanentReqParam  getPermanentTicketReqParam(T sceneData){
        SceneQRTicketPermanentReqParam ret = new SceneQRTicketPermanentReqParam();
        if(sceneData instanceof String) ret.setAction_name(QR_LIMIT_STR_SCENE);
        if(sceneData instanceof Integer) ret.setAction_name(QR_LIMIT_SCENE);
        ret.setAction_info(getQrSceneWrapper(sceneData));
        return ret;
    }

    public static <T> Map getPermanentTicketReqParamMap(T sceneData){
        SceneQRTicketPermanentReqParam permanentTicketReqParam = getPermanentTicketReqParam(sceneData);
        try {
            return beanToMap(permanentTicketReqParam);
        } catch (Exception e) {
            String msg = "将永久二维码ticket请求参数对象转换为Map对象时出现异常：" + e.getMessage();
            throw new BusinessException(msg);
        }
    }

    public static <T> Map getTempTicketReqParamMap(T sceneData){
        SceneQRTicketTempReqParam tempTicketReqParam = getTempTicketReqParam(sceneData);
        try {
            return beanToMap(tempTicketReqParam);
        } catch (Exception e) {
            String msg = "将临时二维码ticket请求参数对象转换为Map对象时出现异常：" + e.getMessage();
            throw new BusinessException(msg);
        }
    }

    private static Map beanToMap(Object object) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(object) : null;
            map.put(key, value);
        }
        return map;
    }
}
